package com.fw.aspect;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.fw.annotation.PrintParam;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;


@Component
@Aspect
@Slf4j(topic = "aspect")
public class RequestAspect {
    //切入点进行切入 execution(* com.fw.controller.*Controller.*Pages(..)) ||
    @Pointcut("execution( * com.fw..*.*(..)) && @annotation(com.fw.annotation.PrintParam)")
    public void pagePoint() {};





    //环绕通知
    @Around(value = "pagePoint()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        //注意； 返回
        Object[] args;
        try {
            args = proceedingJoinPoint.getArgs();
            // 執行打印參數
            MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
            PrintParam annotation = signature.getMethod().getAnnotation(PrintParam.class);
            String methodName = signature.getMethod().getName();
            Object[] temp = Arrays.stream(args).filter(arg -> (!(arg instanceof HttpServletRequest) && !(arg instanceof HttpServletResponse))).toArray();
            TimeInterval timer = DateUtil.timer();
            log.info("方法调用开始: 方法名: {}, 入参: {}", methodName, annotation.input() ? formatParam(temp) : null);
            Object result = proceedingJoinPoint.proceed(args);
            log.info("方法调用结束: 方法名: {},调用时间:{}ms, 回参: {}", methodName, timer.intervalMs(), annotation.output() ? formatParam(result) : null);
            return result;
        } catch (Throwable throwable) {
            log.error(throwable.getMessage());
            throw throwable;
        }
    }

    /**
     * 格式化参数
     */
    private String formatParam(Object result) {
        String afterResult = "内容格式化失败";
        try {
            afterResult = JSONObject.toJSONStringWithDateFormat(result, DatePattern.NORM_DATETIME_PATTERN, SerializerFeature.WriteMapNullValue);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return afterResult;

    }


}

